// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.linqingying.gitcode.authentication.ui

import com.intellij.collaboration.auth.ui.AccountsPanelActionsController
import com.intellij.ide.DataManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.popup.JBPopupFactory
import com.intellij.ui.awt.RelativePoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import com.linqingying.gitcode.api.GitCodeServerPath
import com.linqingying.gitcode.authentication.GCAccountsUtil
import com.linqingying.gitcode.authentication.GCLoginRequest
import com.linqingying.gitcode.authentication.accounts.GCAccountManager
import com.linqingying.gitcode.authentication.accounts.GitCodeAccount
import javax.swing.JComponent

internal class GCAccountsPanelActionsController(private val project: Project, private val model: GCAccountsListModel)
  : AccountsPanelActionsController<GitCodeAccount> {

  override val isAddActionWithPopup: Boolean = true

  override fun addAccount(parentComponent: JComponent, point: RelativePoint?) {
    val loginModel = AccountsListModelLoginModel(model)
    val group = GCAccountsUtil.createAddAccountActionGroup(loginModel, project, parentComponent)


    val actualPoint = point ?: RelativePoint.getCenterOf(parentComponent)
    JBPopupFactory.getInstance()
      .createActionGroupPopup(null, group, DataManager.getInstance().getDataContext(parentComponent),
                              JBPopupFactory.ActionSelectionAid.MNEMONICS, false)
      .show(actualPoint)
  }

  override fun editAccount(parentComponent: JComponent, account: GitCodeAccount) {
    val loginModel = AccountsListModelLoginModel(model, account)
    GCAccountsUtil.login(loginModel,
                         GCLoginRequest(server = account.server, isServerEditable = false),
                         project, parentComponent)
  }

  private class AccountsListModelLoginModel(private val model: GCAccountsListModel,
                                            private val account: GitCodeAccount? = null)
    : GCLoginModel {

    override fun isAccountUnique(server: GitCodeServerPath, login: String): Boolean =
      model.accounts.filter {
        it != account
      }.none {
        it.name == login && it.server.equals(server, true)
      }

    override suspend fun saveLogin(server: GitCodeServerPath, login: String, token: String) {
      withContext(Dispatchers.Main) {
        if (account == null) {
          val account = GCAccountManager.createAccount(login, server)
          model.add(account, token)
        }
        else {
          account.name = login
          model.update(account, token)
        }
      }
    }
  }
}
